package com.gitee.yongzhuzl.commonutil.util.list;

import com.gitee.yongzhuzl.commonutil.util.empty.EmptyUtil;
import com.gitee.yongzhuzl.commonutil.util.reflect.ReflectUtil;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * description: List集合工具类，提供去重、转换、排序、分割等常用操作
 * @author 朱正磊
 * @date 2018-05-23 11:12:11
 */
public class ListUtil {

    /**
     * description: 根据对象指定方法的返回值去重（保留第一个出现的元素）
     * @author 朱正磊
     * @date 2025-08-14 15:43:36
     * @param objectList 待去重的对象集合
     * @param methodName 用于判断重复的方法名（通常是getter方法）
     * @param classes    方法参数类型数组（无参数时为null）
     * @param params     方法参数值数组（无参数时为null）
     * @param <T>        集合元素类型
     * @return 去重后的集合（原集合不改变，返回新集合）
     */
    public static <T> List<T> removeDuplicate(List<T> objectList, String methodName, Class<?>[] classes, Object[] params) {
        if (EmptyUtil.isEmpty(objectList)) {
            return Collections.emptyList();
        }

        Set<Object> seen = new HashSet<>();
        List<T> result = new ArrayList<>(objectList.size());

        for (T item : objectList) {
            Object value = ReflectUtil.invoke(item, methodName, classes, params);
            if (value != null && !seen.contains(value)) {
                seen.add(value);
                result.add(item);
            }
        }
        return result;
    }

    /**
     * description: 根据对象指定无参方法的返回值去重（保留第一个出现的元素）
     * @author 朱正磊
     * @date 2025-08-14 15:43:56
     * @param objectList 待去重的对象集合
     * @param methodName 用于判断重复的无参方法名（通常是getter方法）
     * @param <T>        集合元素类型
     * @return 去重后的集合（原集合不改变，返回新集合）
     */
    public static <T> List<T> removeDuplicate(List<T> objectList, String methodName) {
        return removeDuplicate(objectList, methodName, null, null);
    }

    /**
     * description: 对对象集合去重（基于元素自身的equals方法）
     * @author 朱正磊
     * @date 2025-08-14 15:44:05
     * @param list 待去重的集合
     * @param <T>  集合元素类型
     * @return 去重后的新集合（保留元素首次出现的顺序）
     */
    public static <T> List<T> removeDuplicate(List<T> list) {
        if (EmptyUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        // 使用LinkedHashSet保留顺序，再转为List
        return new ArrayList<>(new LinkedHashSet<>(list));
    }

    /**
     * description: 将迭代器转换为List集合
     * @author 朱正磊
     * @date 2025-08-14 15:44:19
     * @param iterator 待转换的迭代器
     * @param <T>      元素类型
     * @return 转换后的List集合
     */
    public static <T> List<T> iteratorToList(Iterator<T> iterator) {
        if (iterator == null) {
            return Collections.emptyList();
        }
        // 使用Stream简化转换逻辑
        return StreamSupport.stream(
                Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED),
                false
        ).collect(Collectors.toList());
    }

    /**
     * description: 移除集合中所有指定元素
     * @author 朱正磊
     * @date 2025-08-14 15:44:26
     * @param list 待操作的集合
     * @param t    要移除的元素
     * @param <T>  元素类型
     * @return 移除元素后的集合（原集合会被修改）
     */
    public static <T> List<T> removeAll(List<T> list, T t) {
        if (EmptyUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        // 使用Java 8的removeIf简化迭代删除逻辑
        list.removeIf(t::equals);
        return list;
    }

    /**
     * description: 安全获取集合指定索引的元素（避免下标越界异常）
     * @author 朱正磊
     * @date 2025-08-14 15:44:35
     * @param list  集合
     * @param index 索引
     * @param <T>   元素类型
     * @return 索引对应的元素，若索引无效则返回null
     */
    public static <T> T getSafe(List<T> list, int index) {
        if (EmptyUtil.isEmpty(list) || index < 0 || index >= list.size()) {
            return null;
        }
        return list.get(index);
    }

    /**
     * description: 安全设置集合指定索引的元素
     * @author 朱正磊
     * @date 2025-08-14 15:44:43
     * @param list  集合
     * @param index 索引
     * @param t     要设置的元素
     * @param <T>   元素类型
     * @return 设置成功返回true，否则返回false
     */
    public static <T> boolean setSafe(List<T> list, int index, T t) {
        if (EmptyUtil.isEmpty(list) || index < 0 || index >= list.size()) {
            return false;
        }
        list.set(index, t);
        return true;
    }

    /**
     * description: 向集合添加元素（支持指定位置）
     * @author 朱正磊
     * @date 2025-08-14 15:44:54
     * @param list  集合
     * @param t     要添加的元素
     * @param index 位置索引（null表示添加到末尾）
     * @param <T>   元素类型
     * @return 添加后的集合（原集合会被修改）
     */
    public static <T> List<T> addElement(List<T> list, T t, Integer index) {
        if (list == null || t == null) {
            return Collections.emptyList();
        }
        if (index == null) {
            list.add(t);
        } else if (index >= 0 && index <= list.size()) {
            // 允许添加到末尾（index = size）
            list.add(index, t);
        }
        return list;
    }

    /**
     * description: 从集合移除元素（支持按元素或索引）
     * @author 朱正磊
     * @date 2025-08-14 15:45:06
     * @param list  集合
     * @param t     要移除的元素（优先按元素移除）
     * @param index 要移除的索引（元素为null时按索引移除）
     * @param <T>   元素类型
     * @return 移除后的集合（原集合会被修改）
     */
    public static <T> List<T> removeElement(List<T> list, T t, Integer index) {
        if (EmptyUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        if (t != null) {
            list.remove(t);
        } else if (index != null && index >= 0 && index < list.size()) {
            for (int i = list.size() - 1; i >= 0; i--) {
                if (i == index) {
                    list.remove(i);
                }
            }
        }
        return list;
    }

    /**
     * description: 对集合进行升序排序（元素需实现Comparable接口）
     * @author 朱正磊
     * @date 2025-08-14 15:45:37
     * @param list 待排序的集合
     * @param <T>  元素类型（必须实现Comparable）
     * @return 排序后的新集合（原集合不改变）
     */
    public static <T extends Comparable<? super T>> List<T> sortAsc(List<T> list) {
        if (EmptyUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        List<T> sorted = new ArrayList<>(list);
        sorted.sort(Comparable::compareTo);
        return sorted;
    }

    /**
     * description: 对集合进行降序排序（元素需实现Comparable接口）
     * @author 朱正磊
     * @date 2025-08-14 15:45:49
     * @param list 待排序的集合
     * @param <T>  元素类型（必须实现Comparable）
     * @return 排序后的新集合（原集合不改变）
     */
    public static <T extends Comparable<? super T>> List<T> sortDesc(List<T> list) {
        if (EmptyUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        List<T> sorted = new ArrayList<>(list);
        sorted.sort(Collections.reverseOrder());
        return sorted;
    }

    /**
     * description: 将List转换为Set（去重并保留元素首次出现的顺序）
     * @author 朱正磊
     * @date 2025-08-14 15:45:57
     * @param list 待转换的List
     * @param <T>  元素类型
     * @return 包含List元素的LinkedHashSet
     */
    public static <T> Set<T> toOrderedSet(List<T> list) {
        if (EmptyUtil.isEmpty(list)) {
            return Collections.emptySet();
        }
        return new LinkedHashSet<>(list);
    }

    /**
     * description: 获取集合中的最大值（元素需实现Comparable接口）
     * @author 朱正磊
     * @date 2025-08-14 15:46:10
     * @param list 待操作的集合
     * @param <T>  元素类型（必须实现Comparable）
     * @return 集合中的最大值，若集合为空则返回null
     */
    public static <T extends Comparable<? super T>> T getMax(List<T> list) {
        if (EmptyUtil.isEmpty(list)) {
            return null;
        }
        return Collections.max(list);
    }

    /**
     * description: 获取集合中的最小值（元素需实现Comparable接口）
     * @author 朱正磊
     * @date 2025-08-14 15:46:20
     * @param list 待操作的集合
     * @param <T>  元素类型（必须实现Comparable）
     * @return 集合中的最小值，若集合为空则返回null
     */
    public static <T extends Comparable<? super T>> T getMin(List<T> list) {
        if (EmptyUtil.isEmpty(list)) {
            return null;
        }
        return Collections.min(list);
    }

    /**
     * description: 将集合转换为线程安全的集合
     * @author 朱正磊
     * @date 2025-08-14 15:46:29
     * @param list 待转换的集合
     * @param <T>  元素类型
     * @return 线程安全的List
     */
    public static <T> List<T> toSynchronizedList(List<T> list) {
        if (EmptyUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        return Collections.synchronizedList(list);
    }

    /**
     * description: 随机打乱集合元素顺序
     * @author 朱正磊
     * @date 2025-08-14 15:46:38
     * @param list 待打乱的集合
     * @param <T>  元素类型
     * @return 打乱顺序后的集合（原集合会被修改）
     */
    public static <T> List<T> shuffle(List<T> list) {
        if (EmptyUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        Collections.shuffle(list);
        return list;
    }

    /**
     * description: 将集合分割为指定大小的子集合（子集合为独立新集合，不影响原集合）
     * @author 朱正磊
     * @date 2025-08-14 15:46:47
     * @param list 待分割的集合
     * @param subListSize 每个子集合的最大大小
     * @return 分割后的子集合列表
     * @param <T> 元素类型
     */
    public static <T> List<List<T>> splitList(List<T> list, Integer subListSize) {
        List<List<T>> result = new ArrayList<>();
        if (EmptyUtil.isEmpty(list) || subListSize < 1) {
            return result;
        }
        // 元素总个数
        int totalSize = list.size();
        // 子集合的个数
        int batchNum = (totalSize + subListSize - 1) / subListSize;
        for (int i = 0; i < batchNum; i++) {
            int start = i * subListSize;
            int end = Math.min(start + subListSize, totalSize);
            // 复制子列表为新集合
            List<T> subList = new ArrayList<>(list.subList(start, end));
            result.add(subList);
        }
        return result;
    }

    /**
     * 说明：该方法的作用与上面的splitList方法的作用相同
     * description: 将原列表按指定批次大小拆分成子列表
     * @author 朱正磊
     * @date 2025-11-06 15:13:49
     * @param list 原列表
     * @param batchSize 每批元素数量
     * @return 拆分后的列表集合
     * @param <T> 元素类型
     */
    public static <T> List<List<T>> subList(List<T> list, Integer batchSize) {
        List<List<T>> result = new ArrayList<>();
        if (EmptyUtil.isEmpty(list)) {
            throw new RuntimeException("原列表不能为空！");
        }
        if (batchSize <= 0) {
            throw new RuntimeException("每批元素数量必须大于0！");
        }
        // 元素总个数
        int totalSize = list.size();
        // 起始索引
        int start = 0;
        // 循环截取子列表，直到处理完所有元素
        while (start < totalSize) {
            // 计算当前批次的结束索引（取start + batchSize和总长度的较小值，避免越界）
            int end = Math.min(start + batchSize, totalSize);
            // 截取子列表并添加到结果中
            result.add(list.subList(start, end));
            // 移动起始索引到下一批次
            start = end;
        }
        return result;
    }

    /**
     * 说明：该方法的作用与上面的subList方法的作用相同
     * description: 按指定大小，分割集合，将集合按规定个数分为n个部分
     * @author 朱正磊
     * @date 2025-12-02 09:23:03
     * @param list 待分割的集合
     * @param subListSize 指定大小
     * @return 返回分割后的集合
     * @param <T> 元素类型
     */
    public static <T> List<List<T>> partition(List<T> list, Integer subListSize) {
        if (list == null || list.isEmpty() || subListSize < 1) {
            return Collections.emptyList();
        }
        List<List<T>> result = new ArrayList<>();
        int size = list.size();
        int subListNum = (size + subListSize - 1) / subListSize;
        for (int i = 0; i < subListNum; i++) {
            List<T> subList = list.subList(i * subListSize, Math.min((i + 1) * subListSize, size));
            result.add(subList);
        }
        return result;
    }

}
